package main

import (
	"fmt"
	"net"
	"net/http"
	"time"

	"github.com/gorilla/websocket"
)

type (
	Request struct {
		A int
		B int
	}
	Response struct {
		Sum int
	}
)

func home(w http.ResponseWriter, r *http.Request) {
	upgrade := &websocket.Upgrader{
		HandshakeTimeout: 5 * time.Second, //握手超时时间
		ReadBufferSize:   2048,            // 读缓冲大小
		WriteBufferSize:  1024,
	}
	conn, err := upgrade.Upgrade(w, r, nil)
	if err != nil {
		fmt.Printf("upgrade http to websocket error: %v\n", err)
		return
	}
	defer conn.Close()

	for { //长连接
		conn.SetReadDeadline(time.Now().Add(20 * time.Second))
		var request Request
		if err := conn.ReadJSON(&request); err != nil {
			//判断是不是超时
			if netError, ok := err.(net.Error); ok {
				if netError.Timeout() {
					fmt.Printf("read message timeout, remote %s\n", conn.RemoteAddr().String())
					return
				}
			}
			//忽略websocket.CloseGoingAway/websocket.CloseNormalClosure这2种closeErr，如果是其他closeErr就打一条错误日志
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
				fmt.Printf("read message from %s error %v\n", conn.RemoteAddr().String(), err)
			}
			return //只要ReadMessage发生错误，就关闭这条连接
		} else {
			response := Response{Sum: request.A + request.B}
			if err = conn.WriteJSON(&response); err != nil {
				fmt.Printf("write respose failed: %v\n", err)
			} else {
				fmt.Printf("write response %d\n", response.Sum)
			}
		}
	}
}

func main() {
	http.HandleFunc("/", home)
	if err := http.ListenAndServe("127.0.0.1:9999", nil); err != nil {
		fmt.Println(err)
	}
}
